import 'dart:async';
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:flutter/services.dart';

import 'package:get/get.dart';

import 'toast_util.dart';

class CameraUtil{

  static final CameraUtil _singleton = CameraUtil._internal();

  factory CameraUtil() {
    return _singleton;
  }

  CameraUtil._internal();

  RxInt cameraId = RxInt(-1);
  RxBool preview = RxBool(false);
  Size? _previewSize;
  StreamSubscription<CameraErrorEvent>? _errorStreamSubscription;
  StreamSubscription<CameraClosingEvent>? _cameraClosingStreamSubscription;



  Future _fetchCameras() async {
    List<CameraDescription> cameras = <CameraDescription>[];

    try {
      cameras = await CameraPlatform.instance.availableCameras();
      if (cameras.isEmpty) {
        toastError('没有可用的摄像头');
      } else {
        return _initializeCamera(cameras[0 % cameras.length]);
      }
    } on PlatformException catch (e) {
      toastError('${e.message}');
    }
  }

  Future _initializeCamera(CameraDescription camera) async {

    assert(cameraId.value == -1);
    int cId = -1;
    try {
      cId = await CameraPlatform.instance.createCamera(
        camera,
        ResolutionPreset.veryHigh,
        enableAudio: false,
      );
      unawaited(_errorStreamSubscription?.cancel());
      _errorStreamSubscription = CameraPlatform.instance
          .onCameraError(cId)
          .listen((e){
        // if (mounted) {
        disposeCurrentCamera();
        _fetchCameras();
        // }
      });

      unawaited(_cameraClosingStreamSubscription?.cancel());
      _cameraClosingStreamSubscription = CameraPlatform.instance
          .onCameraClosing(cId)
          .listen((e){
        disposeCurrentCamera();
      });

      final Future<CameraInitializedEvent> initialized =
          CameraPlatform.instance.onCameraInitialized(cId).first;

      await CameraPlatform.instance.initializeCamera(
        cId,
      );
      final CameraInitializedEvent event = await initialized;
      _previewSize = Size(
        event.previewWidth,
        event.previewHeight,
      );
      cameraId.value = cId;
      return cameraId.value;

    } on CameraException catch (e) {
      print(e);
      try {
        if (cId >= 0) {
          await CameraPlatform.instance.dispose(cId);
        }
      } on CameraException catch (e) {
        toastError('${e.description}');
      }
      cameraId.value = -1;
      return cameraId.value;
    }
  }

  getPreviewSize(){
    return _previewSize!.width/_previewSize!.height;
  }

  Future disposeCurrentCamera() async {
    _errorStreamSubscription?.cancel();
    _errorStreamSubscription = null;
    _cameraClosingStreamSubscription?.cancel();
    _cameraClosingStreamSubscription = null;

    if (cameraId >= 0) {
      try {
        await CameraPlatform.instance.dispose(cameraId.value);
        cameraId.value = -1;
        return cameraId.value;
      } on CameraException catch (e) {
        toastError('${e.description}');
      }
    }
    return -1;
  }

  Future openCamera() async {

    var cameraId = await _fetchCameras();
    return cameraId;
  }



}